package com.mixed.mixedserver.game.network;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mixed.mixedserver.game.entity.GameMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.msgpack.jackson.dataformat.MessagePackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class GameMessageDecoder extends ByteToMessageDecoder {
    private static final Logger logger = LoggerFactory.getLogger(GameMessageDecoder.class);
    private final ObjectMapper objectMapper;
    
    public GameMessageDecoder() {
        this.objectMapper = new ObjectMapper(new MessagePackFactory());
    }
    
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in.readableBytes() < 4) {
            return; // 等待更多数据
        }
        
        // 标记读取位置
        in.markReaderIndex();
        
        // 读取消息长度
        int messageLength = in.readInt();
        
        // 验证消息长度是否合理
        if (messageLength <= 0 || messageLength > 1048576) { // 最大1MB
            logger.error("Invalid message length: {}", messageLength);
            ctx.close(); // 关闭连接
            return;
        }
        
        // 检查是否有足够的数据
        if (in.readableBytes() < messageLength) {
            in.resetReaderIndex(); // 重置读取位置
            return; // 等待更多数据
        }
        
        try {
            // 读取消息数据
            byte[] messageBytes = new byte[messageLength];
            in.readBytes(messageBytes);
            
            // 反序列化消息
            GameMessage message = objectMapper.readValue(messageBytes, GameMessage.class);
            out.add(message);
            
            logger.debug("Decoded message: type={}, playerId={}", 
                message.getType(), message.getPlayerId());
                
        } catch (Exception e) {
            logger.error("Failed to decode message", e);
            // 跳过这个消息，继续处理下一个
            ctx.fireExceptionCaught(e);
        }
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("Decoder exception", cause);
        super.exceptionCaught(ctx, cause);
    }
}